package pe.bf.extranet.dao.impl;

import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
import oracle.jdbc.OracleTypes;
import org.apache.log4j.Logger;

import pe.bf.base.dao.impl.BaseDAOImpl;
import pe.bf.base.types.OutParameter;
import pe.bf.domain.bean.Contacto;
import pe.bf.domain.bean.Departamento;
import pe.bf.domain.bean.Distrito;
import pe.bf.domain.bean.Empresa;
import pe.bf.domain.bean.Provincia;
import pe.bf.domain.exceptions.DomainException;
import pe.bf.extranet.dao.EmpresaDAO;

public class EmpresaDAOImpl extends BaseDAOImpl implements EmpresaDAO {

	Logger logger = Logger.getLogger(EmpresaDAOImpl.class);

	static final String USP_CRE_EMPRESA = "{call PKG_EMPRESA.USP_CRE_EMPRESA(?,?,?,?,?,?,?,?,?,?)}";
	static final String USP_ACT_EMPRESA = "{call PKG_EMPRESA.USP_ACT_EMPRESA(?,?,?,?,?,?,?,?,?,?)}";
	static final String USP_BAJA_EMPRESA = "{call PKG_EMPRESA.USP_BAJA_EMPRESA(?)}";
	static final String USP_CREA_CONTACTO = "{call PKG_EMPRESA.USP_REGISTRA_CONTACTOS(?,?,?,?,?)}";
	static final String USP_ELIMINA_CONTACTO = "{call PKG_EMPRESA.USP_ELIMINA_CONTACTO(?)}";
	static final String USP_LISTAR_EMPRESAS = "{call PKG_EMPRESA.USP_LISTAR_EMPRESAS(?)}";
	static final String USP_LISTAR_CONTACTOS = "{call PKG_EMPRESA.USP_LISTAR_CONTACTOS(?,?)}";
	static final String USP_OBTENER_DISTRITO = "{call PKG_EMPRESA.USP_OBTENER_DISTRITO(?,?)}";
	static final String USP_OBTENER_PROVINCIA = "{call PKG_EMPRESA.USP_OBTENER_PROVINCIA(?,?)}";
	static final String USP_OBTENER_DEPARTAMENTO = "{call PKG_EMPRESA.USP_OBTENER_DEPARTAMENTO(?,?)}";
	static final String USP_LISTAR_EMPRESAS_PORID = "{call PKG_EMPRESA.USP_LISTAR_EMPRESAS_PORID(?,?)}";

	public EmpresaDAOImpl(DataSource dataSource) {
		super(dataSource);
		// TODO Auto-generated constructor stub
	}

	@Override
	public Empresa crearEmpresa(Empresa empresa) throws DomainException {
		empresa.setIdEmpresa(invokeStoreProcedureGetId(USP_CRE_EMPRESA,
				empresa.getRuc(), empresa.getNombres(), empresa.getRubro(),
				empresa.getDistrito(), empresa.getDireccion(),
				empresa.getTelefono1(), empresa.getTelefono2(),
				empresa.getHorario(), empresa.getDia_validar(),
				new OutParameter(OracleTypes.NUMBER)));

		return empresa;
	}

	@Override
	public void limpiarContactos(long idEmpresa) throws DomainException {
		try {
			invokeStoreProcedure(USP_ELIMINA_CONTACTO, idEmpresa);
		} catch (DomainException e) {
			throw new DomainException(e);
		}
	}

	@Override
	public void registrarContacto(long idEmpresa, Contacto contacto)
			throws DomainException {
		try {
			invokeStoreProcedure(USP_CREA_CONTACTO, idEmpresa,
					contacto.getNombres(), contacto.getCargo(),
					contacto.getTelefono(), contacto.getEmail());
		} catch (DomainException e) {
			throw new DomainException(e);
		}
	}

	@Override
	public void crearEmpresaBatch(List<Empresa> empresaList)
			throws DomainException {

		for (Empresa empresa : empresaList) {
			crearEmpresa(empresa);
		}

	}

	@Override
	public Empresa bajaEmpresa(Empresa empresa) throws DomainException {
		invokeStoreProcedure(USP_BAJA_EMPRESA, empresa.getIdEmpresa());

		return empresa;
	}

	@Override
	public Empresa actualizarEmpresa(Empresa empresa) throws DomainException {
		empresa.setIdEmpresa(invokeStoreProcedureGetId(USP_ACT_EMPRESA,
				empresa.getIdEmpresa(), empresa.getRuc(), empresa.getNombres(),
				empresa.getRubro(), empresa.getDistrito(),
				empresa.getDireccion(), empresa.getTelefono1(),
				empresa.getTelefono2(), empresa.getHorario(),
				empresa.getDia_validar()));

		return empresa;
	}

	@Override
	public List<Empresa> listarEmpresas() throws DomainException {

		CallableStatement cal = invokeStoreProcedureCallable(
				USP_LISTAR_EMPRESAS, new OutParameter(OracleTypes.CURSOR));
		ResultSet resultSet = null;
		List<Empresa> empresaList = null;
		try {
			empresaList = new ArrayList<Empresa>();
			resultSet = (ResultSet) cal.getObject(1);
			while (resultSet.next()) {
				Empresa empresa = new Empresa();
				empresa.setIdEmpresa(resultSet.getLong("id_empresa"));
				empresa.setDireccion(resultSet.getString("direccion"));
				empresa.setRuc(resultSet.getString("ruc"));
				empresa.setEstado(resultSet.getString("estado"));
				empresa.setHorario(resultSet.getString("horario"));
				empresa.setNombres(resultSet.getString("nombres"));
				empresa.setTelefono1(resultSet.getString("telefono1"));
				empresa.setTelefono2(resultSet.getString("telefono2"));
				empresa.setRubro(resultSet.getString("rubro"));
				empresa.setDia_validar(resultSet.getString("dia_validar"));
				empresa.setDistrito(buscarDistrito(resultSet
						.getLong("id_distrito")));
				empresaList.add(empresa);
			}
		} catch (SQLException e) {
			throw new DomainException(e);
		} finally {
			try {
				cal.getConnection().close();
				cal.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}

		}
		return empresaList;
	}

	@Override
	public List<Empresa> buscarEmpresa(Empresa empresaBean)
			throws DomainException {

		CallableStatement cal = invokeStoreProcedureCallable(
				USP_LISTAR_EMPRESAS_PORID, empresaBean.getIdEmpresa(),
				new OutParameter(OracleTypes.CURSOR));
		ResultSet resultSet = null;
		List<Empresa> empresaList = null;
		try {
			empresaList = new ArrayList<Empresa>();
			resultSet = (ResultSet) cal.getObject(2);
			while (resultSet.next()) {
				Empresa empresa = new Empresa();
				empresa.setIdEmpresa(resultSet.getLong("id_empresa"));
				empresa.setDireccion(resultSet.getString("direccion"));
				empresa.setRuc(resultSet.getString("ruc"));
				empresa.setEstado(resultSet.getString("estado"));
				empresa.setHorario(resultSet.getString("horario"));
				empresa.setNombres(resultSet.getString("nombres"));
				empresa.setTelefono1(resultSet.getString("telefono1"));
				empresa.setTelefono2(resultSet.getString("telefono2"));
				empresa.setRubro(resultSet.getString("rubro"));
				empresa.setDia_validar(resultSet.getString("dia_validar"));
				empresa.setDistrito(buscarDistrito(resultSet
						.getLong("id_distrito")));
				empresaList.add(empresa);
			}

			System.out.println("empresas por id " + empresaList.size());
		} catch (SQLException e) {
			throw new DomainException(e);
		} finally {
			try {
				cal.getConnection().close();
				cal.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}

		}
		return empresaList;
	}

	private Provincia buscarProvincia(long long1) throws DomainException {
		Provincia provincia = null;
		CallableStatement cal = invokeStoreProcedureCallable(
				USP_OBTENER_PROVINCIA, long1, new OutParameter(
						OracleTypes.CURSOR));// porque se puso una constante
												// aqui?
		ResultSet resultSet = null;
		try {
			resultSet = (ResultSet) cal.getObject(2);
			while (resultSet.next()) {
				provincia = new Provincia();
				provincia.setIdProvincia(resultSet.getLong("id_provincia"));
				provincia.setDescripcion(resultSet.getString("descripcion"));
				provincia.setDepartamento(buscarDepartamento(resultSet
						.getLong("id_departamento")));
			}
		} catch (SQLException e) {
			throw new DomainException(e);
		} finally {
			try {
				cal.getConnection().close();
				cal.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
		return provincia;
	}

	private Departamento buscarDepartamento(long long1) throws DomainException {
		Departamento departamento = null;
		CallableStatement cal = invokeStoreProcedureCallable(
				USP_OBTENER_DEPARTAMENTO, long1, new OutParameter(
						OracleTypes.CURSOR));// porque se puso una constante
												// aqui?
		ResultSet resultSet = null;
		try {
			resultSet = (ResultSet) cal.getObject(2);

			while (resultSet.next()) {
				departamento = new Departamento();
				departamento.setIdDepartamento(resultSet
						.getLong("id_departamento"));
				departamento.setDescripcion(resultSet.getString("descripcion"));
			}
		} catch (SQLException e) {
			throw new DomainException(e);
		} finally {
			try {
				cal.getConnection().close();
				cal.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
		return departamento;
	}

	private Distrito buscarDistrito(long long1) throws DomainException {
		Distrito distrito = null;
		CallableStatement cal = invokeStoreProcedureCallable(
				USP_OBTENER_DISTRITO, long1, new OutParameter(
						OracleTypes.CURSOR));// porque se puso una constante
												// aqui?
		ResultSet resultSet = null;
		try {

			resultSet = (ResultSet) cal.getObject(2);

			while (resultSet.next()) {
				distrito = new Distrito();
				distrito.setIdDistrito(resultSet.getLong("id_distrito"));
				distrito.setDescripcion(resultSet.getString("descripcion"));
				distrito.setProvincia(buscarProvincia(resultSet
						.getLong("id_provincia")));
			}
		} catch (SQLException e) {
			throw new DomainException(e);
		} finally {
			try {
				cal.getConnection().close();
				cal.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
		return distrito;
	}

	@Override
	public List<Contacto> listarContactosEmpresas(Empresa empresa)
			throws DomainException {

		List<Contacto> contactoList = null;

		try {

			CallableStatement cal = invokeStoreProcedureCallable(
					USP_LISTAR_CONTACTOS, empresa.getIdEmpresa(),
					new OutParameter(OracleTypes.CURSOR));
			ResultSet resultSet = null;
			resultSet = (ResultSet) cal.getObject(2);
			contactoList = new ArrayList<Contacto>();
			while (resultSet.next()) {
				Contacto contacto = new Contacto();
				contacto.setIdContacto(resultSet.getLong("id_contacto"));
				contacto.setNombres(resultSet.getString("nombres"));
				contacto.setCargo(resultSet.getString("cargo"));
				contacto.setTelefono(resultSet.getString("telefono"));
				contacto.setEmail(resultSet.getString("email"));
				contactoList.add(contacto);
			}

			try {
				cal.getConnection().close();
				cal.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		} catch (Exception e) {
			throw new DomainException(e);
		}
		return contactoList;
	}

	@Override
	public void actualizarEmpresaBatch(List<Empresa> empresaList)
			throws DomainException {

	}

}
